home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / objnam.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  48.5 KB  |  1,971 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)objnam.c    3.1    93/05/15    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. /* "an uncursed partly eaten guardian naga hatchling corpse" */
  8. #define    PREFIX    50
  9. #define SCHAR_LIM 127
  10.  
  11. STATIC_DCL char *FDECL(strprepend,(char *,const char *));
  12.  
  13. struct Jitem {
  14.     int item;
  15.     const char *name;
  16. };
  17.  
  18. #ifndef OVLB
  19.  
  20. STATIC_DCL struct Jitem Japanese_items[];
  21.  
  22. #else /* OVLB */
  23.  
  24. STATIC_OVL struct Jitem Japanese_items[] = {
  25.     { SHORT_SWORD, "wakizashi" },
  26.     { BROADSWORD, "ninja-to" },
  27.     { FLAIL, "nunchaku" },
  28.     { GLAIVE, "naginata" },
  29.     { LOCK_PICK, "osaku" },
  30.     { WOODEN_HARP, "koto" },
  31.     { KNIFE, "shito" },
  32.     { PLATE_MAIL, "tanko" },
  33.     { HELMET, "kabuto" },
  34.     { LEATHER_GLOVES, "yugake" },
  35.     { FOOD_RATION, "gunyoki" },
  36.     { POT_BOOZE, "sake" },
  37.     {0, "" }
  38. };
  39.  
  40. #endif /* OVLB */
  41.  
  42. STATIC_DCL const char *FDECL(Japanese_item_name,(int i));
  43.  
  44. #ifdef OVL1
  45.  
  46. STATIC_OVL char *
  47. strprepend(s,pref)
  48. register char *s;
  49. register const char *pref; {
  50. register int i = strlen(pref);
  51.     if(i > PREFIX) {
  52.         pline("WARNING: prefix too short.");
  53.         return(s);
  54.     }
  55.     s -= i;
  56.     (void) strncpy(s, pref, i);    /* do not copy trailing 0 */
  57.     return(s);
  58. }
  59.  
  60. #endif /* OVL1 */
  61. #ifdef OVLB
  62.  
  63. char *
  64. typename(otyp)
  65. register int otyp;
  66. {
  67. #ifdef LINT    /* static char buf[BUFSZ]; */
  68. char buf[BUFSZ];
  69. #else
  70. static char NEARDATA buf[BUFSZ];
  71. #endif
  72. register struct objclass *ocl = &objects[otyp];
  73. register const char *actualn = OBJ_NAME(*ocl);
  74. register const char *dn = OBJ_DESCR(*ocl);
  75. register const char *un = ocl->oc_uname;
  76. register int nn = ocl->oc_name_known;
  77.  
  78.     if (pl_character[0] == 'S' && Japanese_item_name(otyp))
  79.         actualn = Japanese_item_name(otyp);
  80.     switch(ocl->oc_class) {
  81.     case GOLD_CLASS:
  82.         Strcpy(buf, "coin");
  83.         break;
  84.     case POTION_CLASS:
  85.         Strcpy(buf, "potion");
  86.         break;
  87.     case SCROLL_CLASS:
  88.         Strcpy(buf, "scroll");
  89.         break;
  90.     case WAND_CLASS:
  91.         Strcpy(buf, "wand");
  92.         break;
  93.     case SPBOOK_CLASS:
  94.         Strcpy(buf, "spellbook");
  95.         break;
  96.     case RING_CLASS:
  97.         Strcpy(buf, "ring");
  98.         break;
  99.     case AMULET_CLASS:
  100.         if(nn)
  101.             Strcpy(buf,actualn);
  102.         else
  103.             Strcpy(buf,"amulet");
  104.         if(un)
  105.             Sprintf(eos(buf)," called %s",un);
  106.         if(dn)
  107.             Sprintf(eos(buf)," (%s)",dn);
  108.         return(buf);
  109.     default:
  110.         if(nn) {
  111.             Strcpy(buf, actualn);
  112.             if(otyp >= TURQUOISE && otyp <= JADE)
  113.                 Strcat(buf, " stone");
  114.             if(un)
  115.                 Sprintf(eos(buf), " called %s", un);
  116.             if(dn)
  117.                 Sprintf(eos(buf), " (%s)", dn);
  118.         } else {
  119.             Strcpy(buf, dn ? dn : actualn);
  120.             if(ocl->oc_class == GEM_CLASS) {
  121.                 if (otyp == LOADSTONE || otyp == LUCKSTONE)
  122.                     Strcat(buf, " stone");
  123.                 else
  124.                     Strcat(buf, " gem");
  125.             }
  126.             if(un)
  127.                 Sprintf(eos(buf), " called %s", un);
  128.         }
  129.         return(buf);
  130.     }
  131.     /* here for ring/scroll/potion/wand */
  132.     if(nn)
  133.         Sprintf(eos(buf), " of %s", actualn);
  134.     if(un)
  135.         Sprintf(eos(buf), " called %s", un);
  136.     if(dn)
  137.         Sprintf(eos(buf), " (%s)", dn);
  138.     return(buf);
  139. }
  140.  
  141. boolean
  142. obj_is_pname(obj)
  143. register struct obj *obj;
  144. {
  145.     return((boolean)(obj->dknown && obj->known && obj->onamelth && obj->oartifact &&
  146.         !objects[obj->otyp].oc_unique));
  147. }
  148.  
  149. /* Give the name of an object seen at a distance.  Unlike xname/doname,
  150.  * we don't want to set dknown if it's not set already.  The kludge used is
  151.  * to temporarily set Blind so that xname() skips the dknown setting.  This
  152.  * assumes that we don't want to do this too often; if this function becomes
  153.  * frequently used, it'd probably be better to pass a parameter to xname()
  154.  * or doname() instead.
  155.  */
  156. char *
  157. distant_name(obj, func)
  158. register struct obj *obj;
  159. char *FDECL((*func), (OBJ_P));
  160. {
  161.     char *str;
  162.  
  163.     long save_Blinded = Blinded;
  164.     Blinded = 1;
  165.     str = (*func)(obj);
  166.     Blinded = save_Blinded;
  167.     return str;
  168. }
  169.  
  170. #endif /* OVLB */
  171. #ifdef OVL1
  172.  
  173. char *
  174. xname(obj)
  175. register struct obj *obj;
  176. {
  177. #ifdef LINT    /* lint may handle static decl poorly -- static char bufr[]; */
  178.     char bufr[BUFSZ];
  179. #else
  180.     static char bufr[BUFSZ];
  181. #endif
  182.     register char *buf = &(bufr[PREFIX]);    /* leave room for "17 -3 " */
  183.     register int typ = obj->otyp;
  184.     register int nn = objects[typ].oc_name_known;
  185.     register const char *actualn = OBJ_NAME(objects[typ]);
  186.     register const char *dn = OBJ_DESCR(objects[typ]);
  187.     register const char *un = objects[typ].oc_uname;
  188.  
  189.     if (pl_character[0] == 'S' && Japanese_item_name(typ))
  190.         actualn = Japanese_item_name(typ);
  191.  
  192.     buf[0] = '\0';
  193.     if (!Blind) obj->dknown = TRUE;
  194.     if (pl_character[0] == 'P') obj->bknown = TRUE;
  195.     if (obj_is_pname(obj))
  196.         goto nameit;
  197.     switch (obj->oclass) {
  198.         case AMULET_CLASS:
  199.         if (!obj->dknown)
  200.             Strcpy(buf, "amulet");
  201.         else if (typ == FAKE_AMULET_OF_YENDOR)
  202.             /* each must be identified individually */
  203.             Strcpy(buf, obj->known ? actualn : dn);
  204.         else if (nn) /* should be true for the Amulet of Yendor */
  205.             Strcpy(buf, actualn);
  206.         else if (un)
  207.             Sprintf(buf,"amulet called %s", un);
  208.         else
  209.             Sprintf(buf,"%s amulet", dn);
  210.         break;
  211.         case WEAPON_CLASS:
  212.         if (typ <= SHURIKEN && obj->opoisoned)
  213.             Strcpy(buf, "poisoned ");
  214.         case VENOM_CLASS:
  215.         case TOOL_CLASS:
  216.         if(un) {
  217.             /* un must come first here.  If it does not, they could
  218.              * tell objects apart by seeing which ones refuse to
  219.              * accept names.
  220.              */
  221.             Sprintf(buf, "%s called %s",
  222.                 nn ? actualn : dn, un);
  223.         } else if(nn)
  224.             Strcat(buf, actualn);
  225.         else
  226.             Strcat(buf, dn);
  227.         /* If we use an() here we'd have to remember never to use */
  228.         /* it whenever calling doname() or xname(). */
  229.         if (typ == FIGURINE)
  230.             Sprintf(eos(buf), " of a%s %s",
  231.             index(vowels,*(mons[obj->corpsenm].mname)) ? "n" : "",
  232.             mons[obj->corpsenm].mname);
  233.         break;
  234.         case ARMOR_CLASS:
  235.         /* depends on order of the dragon scales objects */
  236.         if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) {
  237.             Sprintf(buf, "set of %s", OBJ_NAME(objects[typ]));
  238.             break;
  239.         }
  240.         if(is_boots(obj) || is_gloves(obj)) Strcpy(buf,"pair of ");
  241.  
  242.         if(nn)    Strcat(buf, actualn);
  243.         else if(un) {
  244.             if(is_boots(obj))
  245.                 Strcat(buf,"boots");
  246.             else if(is_gloves(obj))
  247.                 Strcat(buf,"gloves");
  248.             else if(is_cloak(obj))
  249.                 Strcpy(buf,"cloak");
  250.             else if(is_helmet(obj))
  251.                 Strcpy(buf,"helmet");
  252.             else if(is_shield(obj))
  253.                 Strcpy(buf,"shield");
  254.             else
  255.                 Strcpy(buf,"armor");
  256.             Strcat(buf, " called ");
  257.             Strcat(buf, un);
  258.         } else    Strcat(buf, dn);
  259.         break;
  260.         case FOOD_CLASS:
  261. #ifdef TUTTI_FRUTTI
  262.         if (typ == SLIME_MOLD) {
  263.             register struct fruit *f;
  264.  
  265.             for(f=ffruit; f; f = f->nextf) {
  266.                 if(f->fid == obj->spe) {
  267.                     Strcpy(buf, f->fname);
  268.                     break;
  269.                 }
  270.             }
  271.             if (!f) impossible("Bad fruit #%d?", obj->spe);
  272.             break;
  273.         }
  274. #endif
  275.         Strcpy(buf, actualn);
  276.         if (typ == TIN && obj->known) {
  277.             if(obj->spe > 0)
  278.             Strcat(buf, " of spinach");
  279.             else if (obj->corpsenm < 0)
  280.                 Strcpy(buf, "empty tin");
  281.             else if (is_meaty(&mons[obj->corpsenm]))
  282.             Sprintf(eos(buf), " of %s meat", mons[obj->corpsenm].mname);
  283.             else
  284.             Sprintf(eos(buf), " of %s", mons[obj->corpsenm].mname);
  285.         }
  286.         break;
  287.         case GOLD_CLASS:
  288.         case CHAIN_CLASS:
  289.         Strcpy(buf, actualn);
  290.         break;
  291.         case ROCK_CLASS:
  292.         if (typ == STATUE)
  293.             Sprintf(buf, "%s of %s%s", actualn,
  294.             type_is_pname(&mons[obj->corpsenm]) ? "" :
  295.                 (index(vowels,*(mons[obj->corpsenm].mname)) ?
  296.                                 "an " : "a "),
  297.             mons[obj->corpsenm].mname);
  298.         else Strcpy(buf, actualn);
  299.         break;
  300.         case BALL_CLASS:
  301.         Sprintf(buf, "%sheavy iron ball",
  302.             (obj->owt > objects[typ].oc_weight) ? "very " : "");
  303.         break;
  304.         case POTION_CLASS:
  305.         if(nn || un || !obj->dknown) {
  306.             Strcpy(buf, "potion");
  307.             if(!obj->dknown) break;
  308.             if(nn) {
  309.                 Strcat(buf, " of ");
  310.                 if (typ == POT_WATER &&
  311.                 objects[POT_WATER].oc_name_known &&
  312.                 obj->bknown && (obj->blessed || obj->cursed)) {
  313.                 Strcat(buf, obj->blessed ? "holy " : "unholy ");
  314.                 }
  315.                 Strcat(buf, actualn);
  316.             } else {
  317.                 Strcat(buf, " called ");
  318.                 Strcat(buf, un);
  319.             }
  320.         } else {
  321.             Strcpy(buf, dn);
  322.             Strcat(buf, " potion");
  323.         }
  324.         break;
  325.     case SCROLL_CLASS:
  326.         Strcpy(buf, "scroll");
  327.         if(!obj->dknown) break;
  328.         if(nn) {
  329.             Strcat(buf, " of ");
  330.             Strcat(buf, actualn);
  331.         } else if(un) {
  332.             Strcat(buf, " called ");
  333.             Strcat(buf, un);
  334.         } else if (objects[typ].oc_magic) {
  335.             Strcat(buf, " labeled ");
  336.             Strcat(buf, dn);
  337.         } else {
  338.             Strcpy(buf, dn);
  339.             Strcat(buf, " scroll");
  340.         }
  341.         break;
  342.     case WAND_CLASS:
  343.         if(!obj->dknown)
  344.             Strcpy(buf, "wand");
  345.         else if(nn)
  346.             Sprintf(buf, "wand of %s", actualn);
  347.         else if(un)
  348.             Sprintf(buf, "wand called %s", un);
  349.         else
  350.             Sprintf(buf, "%s wand", dn);
  351.         break;
  352.     case SPBOOK_CLASS:
  353.         if (!obj->dknown) {
  354.             Strcpy(buf, "spellbook");
  355.         } else if (nn) {
  356.             if (typ != SPE_BOOK_OF_THE_DEAD)
  357.                 Strcpy(buf, "spellbook of ");
  358.             Strcat(buf, actualn);
  359.         } else if (un) {
  360.             Sprintf(buf, "spellbook called %s", un);
  361.         } else
  362.             Sprintf(buf, "%s spellbook", dn);
  363.         break;
  364.     case RING_CLASS:
  365.         if(!obj->dknown)
  366.             Strcpy(buf, "ring");
  367.         else if(nn)
  368.             Sprintf(buf, "ring of %s", actualn);
  369.         else if(un)
  370.             Sprintf(buf, "ring called %s", un);
  371.         else
  372.             Sprintf(buf, "%s ring", dn);
  373.         break;
  374.     case GEM_CLASS:
  375.         if(!obj->dknown) {
  376.             if (typ == ROCK || typ == LOADSTONE || typ == LUCKSTONE)
  377.                 Strcpy(buf, "stone");
  378.             else
  379.                 Strcpy(buf, "gem");
  380.             break;
  381.         }
  382.         if(!nn) {
  383.             const char *rock =
  384.               (typ==LOADSTONE || typ==LUCKSTONE) ? "stone" : "gem";
  385.             if(un)    Sprintf(buf,"%s called %s", rock, un);
  386.             else    Sprintf(buf, "%s %s", dn, rock);
  387.             break;
  388.         }
  389.         Strcpy(buf, actualn);
  390.         if(typ >= TURQUOISE && typ <= JADE)
  391.             Strcat(buf, " stone");
  392.         break;
  393.     default:
  394.         Sprintf(buf,"glorkum %d %d %d", obj->oclass, typ, obj->spe);
  395.     }
  396.     if (obj->quan != 1L) Strcpy(buf, makeplural(buf));
  397.  
  398.     if (obj->onamelth &&
  399.         (!obj->oartifact || !objects[obj->otyp].oc_unique)) {
  400.         Strcat(buf, " named ");
  401.         nameit:
  402.         Strcat(buf, ONAME(obj));
  403.     }
  404.  
  405.     if (!strncmpi(buf, "the ", 4)) buf += 4;
  406.     return(buf);
  407. }
  408.  
  409. #endif /* OVL1 */
  410. #ifdef OVL0
  411.  
  412. char *
  413. doname(obj)
  414. register struct obj *obj;
  415. {
  416.     boolean ispoisoned = FALSE;
  417.     char prefix[PREFIX];
  418.     char tmpbuf[PREFIX+1];
  419.     /* when we have to add something at the start of prefix instead of the
  420.      * end (Strcat is used on the end)
  421.      */
  422.     register char *bp = xname(obj);
  423.  
  424.     /* When using xname, we want "poisoned arrow", and when using
  425.      * doname, we want "poisoned +0 arrow".  This kludge is about the only
  426.      * way to do it, at least until someone overhauls xname() and doname(),
  427.      * combining both into one function taking a parameter.
  428.      */
  429.     if (!strncmp(bp, "poisoned ", 9)) {
  430.         bp += 9;
  431.         ispoisoned = TRUE;
  432.     }
  433.  
  434.     if(obj->quan != 1L)
  435.         Sprintf(prefix, "%ld ", obj->quan);
  436.     else if(obj_is_pname(obj)) {
  437.         if (!strncmpi(bp, "the ", 4))
  438.             bp += 4;
  439.         Strcpy(prefix, "the ");
  440.     } else
  441.         Strcpy(prefix, "a ");
  442.  
  443.     if (obj->bknown && 
  444.         obj->oclass != GOLD_CLASS &&
  445.         (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
  446.         || (!obj->cursed && !obj->blessed))) {
  447.         /* allow 'blessed clear potion' if we don't know it's holy water;
  448.          * always allow "uncursed potion of water"
  449.          */
  450.         if (obj->cursed)
  451.         Strcat(prefix, "cursed ");
  452.         else if (obj->blessed)
  453.         Strcat(prefix, "blessed ");
  454.         else if ((!obj->known || !objects[obj->otyp].oc_charged ||
  455.               (obj->oclass == ARMOR_CLASS ||
  456.                obj->oclass == RING_CLASS))
  457.         /* For most items with charges or +/-, if you know how many
  458.          * charges are left or what the +/- is, then you must have
  459.          * totally identified the item, so "uncursed" is unneccesary,
  460.          * because an identified object not described as "blessed" or
  461.          * "cursed" must be uncursed.
  462.          *
  463.          * If the charges or +/- is not known, "uncursed" must be
  464.          * printed to avoid ambiguity between an item whose curse
  465.          * status is unknown, and an item known to be uncursed.
  466.          */
  467. #ifdef MAIL
  468.             && obj->otyp != SCR_MAIL
  469. #endif
  470.             && obj->otyp != FAKE_AMULET_OF_YENDOR
  471.             && obj->otyp != AMULET_OF_YENDOR
  472.             && pl_character[0] != 'P')
  473.         Strcat(prefix, "uncursed ");
  474.     }
  475.  
  476.     if (obj->greased) Strcat(prefix, "greased ");
  477.  
  478.     switch(obj->oclass) {
  479.     case AMULET_CLASS:
  480.         if(obj->otyp == FAKE_AMULET_OF_YENDOR ||
  481.            obj->otyp == AMULET_OF_YENDOR)
  482.             if(strncmp(bp, "cheap ", 6)) {
  483.             Strcpy(tmpbuf, "the ");
  484.             Strcat(tmpbuf, prefix+2); /* skip the "a " */
  485.             Strcpy(prefix, tmpbuf);
  486.             }
  487.         if(obj->owornmask & W_AMUL)
  488.             Strcat(bp, " (being worn)");
  489.         break;
  490.     case WEAPON_CLASS:
  491.         if(ispoisoned)
  492.             Strcat(prefix, "poisoned ");
  493. plus:
  494.         if (obj->oeroded) {
  495.             switch (obj->oeroded) {
  496.                 case 2:    Strcat(prefix, "very "); break;
  497.                 case 3:    Strcat(prefix, "thoroughly "); break;
  498.             }            
  499.             Strcat(prefix,
  500.                    is_rustprone(obj) ? "rusty " :
  501.                    is_corrodeable(obj) ? "corroded " :
  502.                 /* is_flammable(obj) ? "burnt " : "eroded " */
  503.                    "damaged ");
  504.         } else if (obj->rknown && obj->oerodeproof)
  505.             Strcat(prefix,
  506.                    is_rustprone(obj) ? "rustproof " :
  507.                    is_corrodeable(obj) ? "corrodeproof " :    /* "stainless"? */
  508.                    is_flammable(obj) ? "fireproof " : "");
  509.         if(obj->known) {
  510.             Strcat(prefix, sitoa(obj->spe));
  511.             Strcat(prefix, " ");
  512.         }
  513.         break;
  514.     case ARMOR_CLASS:
  515.         if(obj->owornmask & W_ARMOR)
  516.             Strcat(bp,
  517. #ifdef POLYSELF
  518.                 (obj == uskin) ? " (embedded in your skin)" :
  519. #endif
  520.                 " (being worn)");
  521.         goto plus;
  522.     case TOOL_CLASS:        /* temp. hack by GAN 11/18/86 */
  523.         if(obj->owornmask & W_TOOL) { /* blindfold */
  524.             Strcat(bp, " (being worn)");
  525.             break;
  526.         }
  527. #ifdef WALKIES
  528.         if(obj->otyp == LEASH && obj->leashmon != 0) {
  529.             Strcat(bp, " (in use)");
  530.             break;
  531.         }
  532. #endif
  533.         if(obj->otyp == PICK_AXE || obj->otyp == UNICORN_HORN)
  534.             goto plus;
  535.         if (Is_candle(obj) &&
  536.             obj->age < 20L * (long)objects[obj->otyp].oc_cost)
  537.             Strcat(prefix, "partly used ");
  538.         if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
  539.             obj->otyp == BRASS_LANTERN ||
  540.             Is_candle(obj) || obj->otyp == CANDELABRUM_OF_INVOCATION) {
  541.             if(obj->lamplit)
  542.                 Strcat(bp, " (lit)");
  543.             break;
  544.         }
  545.         if(!objects[obj->otyp].oc_charged) break;
  546.         /* if special tool, fall through to show charges */
  547.     case WAND_CLASS:
  548.         if(obj->known)
  549.             Sprintf(eos(bp), " (%d)", obj->spe);
  550.         break;
  551.     case RING_CLASS:
  552.         if(obj->owornmask & W_RINGR) Strcat(bp, " (on right ");
  553.         if(obj->owornmask & W_RINGL) Strcat(bp, " (on left ");
  554.         if(obj->owornmask & W_RING) {
  555.             Strcat(bp, body_part(HAND));
  556.             Strcat(bp, ")");
  557.         }
  558.         if(obj->known && objects[obj->otyp].oc_charged) {
  559.             Strcat(prefix, sitoa(obj->spe));
  560.             Strcat(prefix, " ");
  561.         }
  562.         break;
  563.     case FOOD_CLASS:
  564.         if (obj->oeaten)
  565.             Strcat(prefix, "partly eaten ");
  566.         if (obj->otyp == CORPSE) {
  567.             if (type_is_pname(&mons[obj->corpsenm])) {
  568.             Sprintf(prefix, "%s ",
  569.                 s_suffix(mons[obj->corpsenm].mname));
  570.             if (obj->oeaten) Strcat(prefix, "partly eaten ");
  571.             } else {
  572.             Strcat(prefix, mons[obj->corpsenm].mname);
  573.             Strcat(prefix, " ");
  574.             }
  575.         } else if (obj->otyp == EGG && obj->known) {
  576.             if (obj->corpsenm >= 0) {
  577.             Strcat(prefix, mons[obj->corpsenm].mname);
  578.             Strcat(prefix, " ");
  579. #ifdef POLYSELF
  580.             if (obj->spe)
  581.                 Strcat(bp, " (laid by you)");
  582. #endif
  583.             }
  584.         }
  585.         break;
  586.     case BALL_CLASS:
  587.     case CHAIN_CLASS:
  588.         if (obj->oeroded) {
  589.             switch(obj->oeroded) {
  590.             case 2: Strcat(prefix, "very "); break;
  591.             case 3: Strcat(prefix, "thoroughly "); break;
  592.             }
  593.             Strcat(prefix, "rusty ");
  594.         }
  595.         if(obj->owornmask & W_BALL)
  596.             Strcat(bp, " (chained to you)");
  597.             break;
  598.     }
  599.  
  600.     if((obj->owornmask & W_WEP) && !mrg_to_wielded) {
  601.         if (obj->quan != 1L)
  602.             Strcat(bp, " (wielded)");
  603.         else {
  604.             Strcat(bp, " (weapon in ");
  605.             Strcat(bp, body_part(HAND));
  606.             Strcat(bp, ")");
  607.         }
  608.     }
  609.     if(obj->unpaid)
  610.         Strcat(bp, " (unpaid)");
  611.     if (!strncmp(prefix, "a ", 2) &&
  612.             index(vowels, *(prefix+2) ? *(prefix+2) : *bp)
  613.             && (*(prefix+2) || (strncmp(bp, "uranium", 7)
  614.                 && strncmp(bp, "unicorn", 7)))) {
  615.         Strcpy(tmpbuf, prefix);
  616.         Strcpy(prefix, "an ");
  617.         Strcpy(prefix+3, tmpbuf+2);
  618.     }
  619.     bp = strprepend(bp, prefix);
  620.     return(bp);
  621. }
  622.  
  623. #endif /* OVL0 */
  624. #ifdef OVLB
  625.  
  626. /*
  627.  * Used if only one of a collection of objects is named (e.g. in eat.c).
  628.  */
  629.  
  630. char *
  631. singular(otmp, func)
  632. register struct obj *otmp;
  633. char *FDECL((*func), (OBJ_P));
  634. {
  635.     long savequan;
  636.     char *nam;
  637.  
  638.     /* Note: using xname for corpses will not give the monster type */
  639.     if (otmp->otyp == CORPSE && func == xname) {
  640.         static char NEARDATA buf[31];
  641.  
  642.         Sprintf(buf, "%s corpse", mons[otmp->corpsenm].mname);
  643.         return buf;
  644.     }
  645.     savequan = otmp->quan;
  646.     otmp->quan = 1L;
  647.     nam = (*func)(otmp);
  648.     otmp->quan = savequan;
  649.     return nam;
  650. }
  651.  
  652. char *
  653. an(str)
  654. register const char *str;
  655. {
  656.     static char NEARDATA buf[BUFSZ];
  657.  
  658.     buf[0] = '\0';
  659.  
  660.     if (strncmpi(str, "the ", 4) &&
  661.         strcmp(str, "molten lava") &&
  662.         strcmp(str, "ice"))
  663.             if (index(vowels, *str) &&
  664.             strncmp(str, "useful", 6) &&
  665.             strncmp(str, "unicorn", 7) &&
  666.             strncmp(str, "uranium", 7))
  667.                 Strcpy(buf, "an ");
  668.             else
  669.             Strcpy(buf, "a ");
  670.  
  671.     Strcat(buf, str);
  672.     return buf;
  673. }
  674.  
  675. char *
  676. An(str)
  677. const char *str;
  678. {
  679.     register char *tmp = an(str);
  680.     *tmp = highc(*tmp);
  681.     return tmp;
  682. }
  683.  
  684. /*
  685.  * Prepend "the" if necessary; assumes str is a subject derived from xname.
  686.  * Use type_is_pname() for monster names, not the().  the() is idempotent.
  687.  */
  688. char *
  689. the(str)
  690. const char *str;
  691. {
  692.     static char NEARDATA buf[BUFSZ];
  693.  
  694.     if (!strncmpi(str, "the ", 4)) {
  695.         buf[0] = lowc(*str);
  696.         Strcpy(&buf[1], str+1);
  697.         return buf;
  698.     } else if (*str < 'A' || *str > 'Z') {
  699.         /* not a proper name, needs an article */
  700.         Strcpy(buf, "the ");
  701.     } else {
  702.         /* Probably a proper name, might not need an article */
  703.         register char *tmp;
  704.  
  705.         buf[0] = 0;
  706.  
  707.         /* some objects have capitalized adjectives in their names */
  708.         if(((tmp = rindex(str, ' ')) || (tmp = rindex(str, '-'))) &&
  709.            (tmp[1] < 'A' || tmp[1] > 'Z'))
  710.         Strcpy(buf, "the ");
  711.         else if (tmp && (tmp = index(str, ' ')) != NULL) {
  712.         /* it needs an article if the name contains "of" */
  713.         while(tmp && strncmp(++tmp, "of ", 3))
  714.             tmp = index(tmp, ' ');
  715.         if (tmp) /* found an "of" */
  716.             Strcpy(buf, "the ");
  717.         }
  718.     }
  719.     Strcat(buf, str);
  720.  
  721.     return buf;
  722. }
  723.  
  724. char *
  725. The(str)
  726. const char *str;
  727. {
  728.     register char *tmp = the(str);
  729.     *tmp = highc(*tmp);
  730.     return tmp;
  731. }
  732.  
  733. char *
  734. aobjnam(otmp,verb)
  735. register struct obj *otmp;
  736. register const char *verb;
  737. {
  738.     register char *bp = xname(otmp);
  739.     char prefix[PREFIX];
  740.  
  741.     if(otmp->quan != 1L) {
  742.         Sprintf(prefix, "%ld ", otmp->quan);
  743.         bp = strprepend(bp, prefix);
  744.     }
  745.  
  746.     if(verb) {
  747.         /* verb is given in plural (without trailing s) */
  748.         Strcat(bp, " ");
  749.         if(otmp->quan != 1L)
  750.             Strcat(bp, verb);
  751.         else if(!strcmp(verb, "are"))
  752.             Strcat(bp, "is");
  753.         else {
  754.             Strcat(bp, verb);
  755.             Strcat(bp, "s");
  756.         }
  757.     }
  758.     return(bp);
  759. }
  760.  
  761. char *
  762. Doname2(obj)
  763. register struct obj *obj;
  764. {
  765.     register char *s = doname(obj);
  766.  
  767.     if('a' <= *s && *s <= 'z') *s -= ('a' - 'A');
  768.     return(s);
  769. }
  770.  
  771. static const char *wrp[] = {
  772.     "wand", "ring", "potion", "scroll", "gem", "amulet",
  773.     "spellbook", "spell book",
  774.     /* for non-specific wishes */
  775.     "weapon", "armor", "armour", "tool", "food", "comestible",
  776. };
  777. static const char wrpsym[] = {
  778.     WAND_CLASS, RING_CLASS, POTION_CLASS, SCROLL_CLASS, GEM_CLASS, 
  779.         AMULET_CLASS, SPBOOK_CLASS, SPBOOK_CLASS,
  780.     WEAPON_CLASS, ARMOR_CLASS, ARMOR_CLASS, TOOL_CLASS, FOOD_CLASS,
  781.     FOOD_CLASS
  782. };
  783.  
  784. #endif /* OVLB */
  785. #ifdef OVL0
  786.  
  787. /* Plural routine; chiefly used for user-defined fruits.  We have to try to
  788.  * account for everything reasonable the player has; something unreasonable
  789.  * can still break the code.  However, it's still a lot more accurate than
  790.  * "just add an s at the end", which Rogue uses...
  791.  *
  792.  * Also used for plural monster names ("Wiped out all homunculi.")
  793.  * and body parts.
  794.  *
  795.  * Also misused by muse.c to convert 1st person present verbs to 2nd person.
  796.  */
  797. char *
  798. makeplural(oldstr)
  799. const char *oldstr;
  800. {
  801.     /* Note: cannot use strcmpi here -- it'd give MATZot, CAVEMeN,... */
  802.     register char *spot;
  803.     static char NEARDATA str[BUFSZ];
  804.     const char *excess;
  805.     int len;
  806.  
  807.     while (*oldstr==' ') oldstr++;
  808.     if (!oldstr || !*oldstr) {
  809.         impossible("plural of null?");
  810.         Strcpy(str, "s");
  811.         return str;
  812.     }
  813.     Strcpy(str, oldstr);
  814.  
  815.     /* Search for common compounds, ex. lump of royal jelly */
  816.     for(excess=(char *)0, spot=str; *spot; spot++) {
  817.         if (!strncmp(spot, " of ", 4)
  818.                 || !strncmp(spot, " labeled ", 9)
  819.                 || !strncmp(spot, " called ", 8)
  820.                 || !strncmp(spot, " named ", 7)
  821.                 || !strcmp(spot, " above") /* lurkers above */
  822.                 || !strncmp(spot, " versus ", 8)
  823. #ifdef TUTTI_FRUTTI
  824.                 || !strncmp(spot, " from ", 6)
  825.                 || !strncmp(spot, " in ", 4)
  826.                 || !strncmp(spot, " on ", 4)
  827.                 || !strncmp(spot, " a la ", 6)
  828.                 || !strncmp(spot, " with", 5)    /* " with "? */
  829.                 || !strncmp(spot, " de ", 4)
  830.                 || !strncmp(spot, " d'", 3)
  831.                 || !strncmp(spot, " du ", 4)
  832. #endif
  833.                 ) {
  834.             excess = oldstr + (int) (spot - str);
  835.             *spot = 0;
  836.             break;
  837.         }
  838.     }
  839.     spot--;
  840.     while (*spot==' ') spot--; /* Strip blanks from end */
  841.     *(spot+1) = 0;
  842.     /* Now spot is the last character of the string */
  843.  
  844.     len = strlen(str);
  845. #ifdef TUTTI_FRUTTI
  846.     /* Single letters */
  847.     if (len==1 || !letter(*spot)) {
  848.         Strcpy(spot+1, "'s");
  849.         goto bottom;
  850.     }
  851. #endif
  852.  
  853.     /* man/men ("Wiped out all cavemen.") */
  854.     if (len >= 3 && !strcmp(spot-2, "man") &&
  855.             (len<6 || strcmp(spot-5, "shaman")) &&
  856.             (len<5 || strcmp(spot-4, "human"))) {
  857.         *(spot-1) = 'e';
  858.         goto bottom;
  859.     }
  860.  
  861.     /* tooth/teeth */
  862.     if (len >= 5 && !strcmp(spot-4, "tooth")) {
  863.         Strcpy(spot-3, "eeth");
  864.         goto bottom;
  865.     }
  866.  
  867.     /* knife/knives, etc... */
  868.     if (!strcmp(spot-1, "fe"))
  869.         *(spot-1) = 'v';
  870.     else if (*spot == 'f')
  871.         if (index("lr", *(spot-1)) || index(vowels, *(spot-1)))
  872.             *spot = 'v';
  873.         else if (len >= 5 && !strncmp(spot-4, "staf", 4))
  874.             Strcpy(spot-1, "ve");
  875.  
  876.     /* foot/feet (body part) */
  877.     if (len >= 4 && !strcmp(spot-3, "foot")) {
  878.         Strcpy(spot-2, "eet");
  879.         goto bottom;
  880.     }
  881.  
  882.     /* ium/ia (mycelia, baluchitheria) */
  883.     if (len >= 3 && !strcmp(spot-2, "ium")) {
  884.         *(spot--) = (char)0;
  885.         *spot = 'a';
  886.         goto bottom;
  887.     }
  888.  
  889.     /* algae, larvae, hyphae (another fungus part) */
  890. #ifdef TUTTI_FRUTTI
  891.     if ((len >= 4 && !strcmp(spot-3, "alga")) ||
  892.         (len >= 5 &&
  893.          (!strcmp(spot-4, "hypha") || !strcmp(spot-4, "larva"))))
  894. #else
  895.     if (len >= 5 && (!strcmp(spot-4, "hypha")))
  896. #endif
  897.     {
  898.         Strcpy(spot, "ae");
  899.         goto bottom;
  900.     }
  901.  
  902.     /* fungus/fungi, homunculus/homunculi, but wumpuses */
  903.     if (!strcmp(spot-1, "us") && (len < 6 || strcmp(spot-5, "wumpus"))) {
  904.         *(spot--) = (char)0;
  905.         *spot = 'i';
  906.         goto bottom;
  907.     }
  908.  
  909.     /* vortex/vortices */
  910.     if (len >= 6 && !strcmp(spot-3, "rtex")) {
  911.         Strcpy(spot-1, "ices");
  912.         goto bottom;
  913.     }
  914.  
  915.     /* djinni/djinn (note: also efreeti/efreet) */
  916.     if (len >= 6 && !strcmp(spot-5, "djinni")) {
  917.         *spot = (char)0;
  918.         goto bottom;
  919.     }
  920.  
  921.     /* mumak/mumakil */
  922.     if (len >= 5 && !strcmp(spot-4, "mumak")) {
  923.         Strcpy(spot+1, "il");
  924.         goto bottom;
  925.     }
  926.  
  927.     /* same singular and plural */
  928.     /* note: also swine, trout, grouse */
  929.     if ((len >= 2 && !strcmp(spot-1, "ai")) || /* samurai, Uruk-hai */
  930. #ifdef TUTTI_FRUTTI
  931.         (len >= 5 &&
  932.          (!strcmp(spot-4, "manes") || !strcmp(spot-4, "sheep"))) ||
  933.         (len >= 4 &&
  934.          (!strcmp(spot-3, "fish") || !strcmp(spot-3, "tuna") ||
  935.           !strcmp(spot-3, "deer")))
  936. #else
  937.         (len >= 5 && !strcmp(spot-4, "manes"))
  938. #endif
  939.         ) goto bottom;
  940.  
  941.     /* sis/ses (nemesis) */
  942.     if (len >= 3 && !strcmp(spot-2, "sis")) {
  943.         *(spot-1) = 'e';
  944.         goto bottom;
  945.     }
  946.  
  947. #ifdef TUTTI_FRUTTI
  948.     /* mouse/mice,louse/lice (not a monster, but possible in food names) */
  949.     if (len >= 5 && !strcmp(spot-3, "ouse") && index("MmLl", *(spot-4))) {
  950.         Strcpy(spot-3, "ice");
  951.         goto bottom;
  952.     }
  953.  
  954.     /* matzoh/matzot, possible food name */
  955.     if (len >= 6 && (!strcmp(spot-5, "matzoh")
  956.                     || !strcmp(spot-5, "matzah"))) {
  957.         Strcpy(spot-1, "ot");
  958.         goto bottom;
  959.     }
  960.     if (len >= 5 && (!strcmp(spot-4, "matzo")
  961.                     || !strcmp(spot-5, "matza"))) {
  962.         Strcpy(spot, "ot");
  963.         goto bottom;
  964.     }
  965.  
  966.     /* child/children (for wise guys who give their food funny names) */
  967.     if (len >= 5 && !strcmp(spot-4, "child")) {
  968.         Strcpy(spot, "dren");
  969.         goto bottom;
  970.     }
  971.  
  972.     /* note: -eau/-eaux (gateau, bordeau...) */
  973.     /* note: ox/oxen, VAX/VAXen, goose/geese */
  974. #endif
  975.  
  976.     /* Ends in z, x, s, ch, sh; add an "es" */
  977.     if (index("zxsv", *spot)
  978.             || (len >= 2 && *spot=='h' && index("cs", *(spot-1)))
  979. #ifdef TUTTI_FRUTTI
  980.     /* Kludge to get "tomatoes" and "potatoes" right */
  981.             || (len >= 4 && !strcmp(spot-2, "ato"))
  982. #endif
  983.                                     ) {
  984.         Strcpy(spot+1, "es");
  985.         goto bottom;
  986.     }
  987.  
  988.     /* Ends in y preceded by consonant (note: also "qu") change to "ies" */
  989.     if (*spot == 'y' &&
  990.         (!index(vowels, *(spot-1)))) {
  991.         Strcpy(spot, "ies");
  992.         goto bottom;
  993.     }
  994.  
  995.     /* Japanese words: plurals are the same as singlar */
  996.     if ((len == 2 && !strcmp(str, "ya")) ||
  997.         (len > 2 && !strcmp(spot-2, " ya")) ||
  998.         (len >= 5 && (!strcmp(spot-4, "ninja") ||
  999.             !strcmp(spot-4, "ronin") ||
  1000.             !strcmp(spot-4, "shito") ||
  1001.             !strcmp(spot-4, "tengu"))) ||
  1002.         (len >= 7 && (!strcmp(spot-6, "samurai") ||
  1003.             !strcmp(spot-6, "gunyoki"))))
  1004.         goto bottom;
  1005.  
  1006.     /* Default: append an 's' */
  1007.     Strcpy(spot+1, "s");
  1008.  
  1009. bottom:    if (excess) Strcpy(eos(str), excess);
  1010.     return str;
  1011. }
  1012.  
  1013. #endif /* OVL0 */
  1014.  
  1015. struct o_range {
  1016.     const char *name, osym;
  1017.     int  f_o_range, l_o_range;
  1018. };
  1019.  
  1020. #ifndef OVLB
  1021.  
  1022. STATIC_DCL const struct o_range o_ranges[];
  1023.  
  1024. #else /* OVLB */
  1025.  
  1026. /* wishable subranges of objects */
  1027. STATIC_OVL const struct o_range NEARDATA o_ranges[] = {
  1028.     { "bag",    TOOL_CLASS,   SACK,          BAG_OF_TRICKS },
  1029.     { "candle",    TOOL_CLASS,   TALLOW_CANDLE,  WAX_CANDLE },
  1030.     { "horn",    TOOL_CLASS,   TOOLED_HORN,    HORN_OF_PLENTY },
  1031.     { "gloves",    ARMOR_CLASS,  LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
  1032.     { "gauntlets",    ARMOR_CLASS,  LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
  1033.     { "boots",    ARMOR_CLASS,  LOW_BOOTS,      LEVITATION_BOOTS },
  1034.     { "shoes",    ARMOR_CLASS,  LOW_BOOTS,      IRON_SHOES },
  1035.     { "cloak",    ARMOR_CLASS,  MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
  1036.     { "shield",    ARMOR_CLASS,  SMALL_SHIELD,   SHIELD_OF_REFLECTION },
  1037.     { "helm",    ARMOR_CLASS,  ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
  1038.     { "dragon scales",
  1039.             ARMOR_CLASS,  GRAY_DRAGON_SCALES, YELLOW_DRAGON_SCALES },
  1040.     { "dragon scale mail",
  1041.             ARMOR_CLASS,  GRAY_DRAGON_SCALE_MAIL, YELLOW_DRAGON_SCALE_MAIL },
  1042.     { "sword",    WEAPON_CLASS, SHORT_SWORD,    KATANA },
  1043. #ifdef WIZARD
  1044.     { "venom",    VENOM_CLASS,  BLINDING_VENOM, ACID_VENOM },
  1045. #endif
  1046.     { "grey stone", GEM_CLASS,    LUCKSTONE,      LOADSTONE },
  1047. };
  1048.  
  1049. #define BSTRCMP(base,ptr,string) ((ptr) < base || strcmp((ptr),string))
  1050. #define BSTRCMPI(base,ptr,string) ((ptr) < base || strcmpi((ptr),string))
  1051. #define BSTRNCMP(base,ptr,string,num) ((ptr)<base || strncmp((ptr),string,num))
  1052.  
  1053. /*
  1054.  * Singularize a string the user typed in; this helps reduce the complexity
  1055.  * of readobjnam, and is also used in pager.c to singularize the string
  1056.  * for which help is sought.
  1057.  */
  1058.  
  1059. char *
  1060. makesingular(oldstr)
  1061. const char *oldstr;
  1062. {
  1063.     register char *p, *bp;
  1064.     static char NEARDATA str[BUFSZ];
  1065.  
  1066.     if (!oldstr || !*oldstr) {
  1067.         impossible("singular of null?");
  1068.         str[0] = 0;
  1069.         return str;
  1070.     }
  1071.     Strcpy(str, oldstr);
  1072.     bp = str;
  1073.  
  1074.     while (*bp == ' ') bp++;
  1075.     /* find "cloves of garlic", "worthless pieces of blue glass" */
  1076.     if ((p = strstri(bp, "s of ")) != 0) {
  1077.         /* but don't singularize "gauntlets" */
  1078.         if (BSTRNCMP(bp, p-8, "gauntlet", 8))
  1079.         while ((*p = *(p+1)) != 0) p++;
  1080.         return bp;
  1081.     }
  1082.  
  1083.     /* remove -s or -es (boxes) or -ies (rubies) */
  1084.     p = eos(bp);
  1085.     if (p >= bp+1 && p[-1] == 's') {
  1086.         if (p >= bp+2 && p[-2] == 'e') {
  1087.             if (p >= bp+3 && p[-3] == 'i') {
  1088.                 if(!BSTRCMP(bp, p-7, "cookies") ||
  1089.                    !BSTRCMP(bp, p-4, "pies"))
  1090.                     goto mins;
  1091.                 Strcpy(p-3, "y");
  1092.                 return bp;
  1093.             }
  1094.  
  1095.             /* note: cloves / knives from clove / knife */
  1096.             if(!BSTRCMP(bp, p-6, "knives")) {
  1097.                 Strcpy(p-3, "fe");
  1098.                 return bp;
  1099.             }
  1100.  
  1101.             if(!BSTRCMP(bp, p-6, "staves")) {
  1102.                 Strcpy(p-3, "ff");
  1103.                 return bp;
  1104.             }
  1105.  
  1106.             /* note: nurses, axes but boxes */
  1107.             if(!BSTRCMP(bp, p-5, "boxes")) {
  1108.                 p[-2] = 0;
  1109.                 return bp;
  1110.             }
  1111.             if (!BSTRCMP(bp, p-6, "gloves") ||
  1112.                 !BSTRCMP(bp, p-5, "shoes") ||
  1113.                 !BSTRCMP(bp, p-6, "scales"))
  1114.                 return bp;
  1115.         } else if (!BSTRCMP(bp, p-5, "boots") ||
  1116.                !BSTRCMP(bp, p-6, "tricks") ||
  1117.                !BSTRCMP(bp, p-9, "paralysis") ||
  1118.                !BSTRCMP(bp, p-5, "glass") ||
  1119.                !BSTRCMP(bp, p-4, "ness") ||
  1120.                !BSTRCMP(bp, p-14, "shape changers") ||
  1121.                !BSTRCMP(bp, p-15, "detect monsters") ||
  1122.                !BSTRCMPI(bp, p-11, "Aesculapius"))    /* staff */
  1123.                 return bp;
  1124.     mins:
  1125.         p[-1] = 0;
  1126.     } else {
  1127.         if(!BSTRCMP(bp, p-5, "teeth")) {
  1128.             Strcpy(p-5, "tooth");
  1129.             return bp;
  1130.         }
  1131.         /* here we cannot find the plural suffix */
  1132.     }
  1133.     return bp;
  1134. }
  1135.  
  1136. /* alternate spellings: extra space, space instead of hyphen, etc */
  1137. struct alt_spellings {
  1138.     const char *sp;
  1139.     int ob;
  1140. } spellings[] = {
  1141.     { "two handed sword", TWO_HANDED_SWORD },
  1142.     { "battle axe", BATTLE_AXE },
  1143.     { "lockpick", LOCK_PICK },
  1144.     { "pick axe", PICK_AXE },
  1145.     { "luck stone", LUCKSTONE },
  1146.     { "load stone", LOADSTONE },
  1147.     { "broad sword", BROADSWORD },
  1148.     { "elven broad sword", ELVEN_BROADSWORD },
  1149.     { "longsword", LONG_SWORD },
  1150.     { "shortsword", SHORT_SWORD },
  1151.     { "elven shortsword", ELVEN_SHORT_SWORD },
  1152.     { "dwarvish shortsword", DWARVISH_SHORT_SWORD },
  1153.     { "orcish shortsword", ORCISH_SHORT_SWORD },
  1154.     { "warhammer", WAR_HAMMER },
  1155.     { "grey dragon scale mail", GRAY_DRAGON_SCALE_MAIL },
  1156.     { "grey dragon scales", GRAY_DRAGON_SCALES },
  1157.     { "enchant armour", SCR_ENCHANT_ARMOR },
  1158.     { "destroy armour", SCR_DESTROY_ARMOR },
  1159.     { "scroll of enchant armour", SCR_ENCHANT_ARMOR },
  1160.     { "scroll of destroy armour", SCR_DESTROY_ARMOR },
  1161.     { "leather armour", LEATHER_ARMOR },
  1162.     { "studded leather armour", STUDDED_LEATHER_ARMOR },
  1163.     { "iron ball", HEAVY_IRON_BALL },
  1164.     { "stone", ROCK },
  1165.     { (const char *)0, 0 },
  1166. };
  1167.  
  1168. /* Return something wished for.  If not an object, return &zeroobj; if an error
  1169.  * (no matching object), return (struct obj *)0.  Giving readobjnam() a null
  1170.  * pointer skips the error return and creates a random object instead.
  1171.  */
  1172. struct obj *
  1173. readobjnam(bp)
  1174. register char *bp;
  1175. {
  1176.     register char *p;
  1177.     register int i;
  1178.     register struct obj *otmp;
  1179.     int cnt, spe, spesgn, typ, very;
  1180.     int blessed, uncursed, iscursed, ispoisoned;
  1181.     int eroded, erodeproof;
  1182.     int halfeaten, mntmp, contents;
  1183.     int islit, unlabeled;
  1184. #ifdef TUTTI_FRUTTI
  1185.     struct fruit *f;
  1186.     int ftype = current_fruit;
  1187.     char fruitbuf[BUFSZ];
  1188.     /* We want to check for fruits last so that, for example, someone
  1189.      * who names their fruit "katana" and wishes for a katana gets a real
  1190.      * one.  But, we have to keep around the old buf since in the meantime
  1191.      * we have deleted "empty", "+6", etc...
  1192.      */
  1193. #endif
  1194.     char let;
  1195.     char *un, *dn, *actualn;
  1196.     const char *name=0;
  1197.  
  1198.     cnt = spe = spesgn = typ = very = blessed = uncursed =
  1199.         iscursed = ispoisoned = eroded = erodeproof = halfeaten =
  1200.         islit = unlabeled = 0;
  1201.     mntmp = -1;
  1202. #define UNDEFINED 0
  1203. #define EMPTY 1
  1204. #define SPINACH 2
  1205.     contents = UNDEFINED;
  1206.     let = 0;
  1207.     actualn = dn = un = 0;
  1208.  
  1209.     /* first, remove extra whitespace they may have typed */
  1210.     if (bp) {
  1211.         char c, *p2;
  1212.         boolean was_space = TRUE;
  1213.  
  1214.         for (p = p2 = bp; (c = *p) != '\0'; p++) {
  1215.              /* if (c == '\t') c = ' '; */
  1216.             if (c != ' ' || !was_space)  *p2++ = c;
  1217.             was_space = (c == ' ');
  1218.         }
  1219.         if (was_space && p2 > bp)  p2--;
  1220.         *p2 = '\0';
  1221.     }
  1222.  
  1223.     for(;;) {
  1224.         register int l;
  1225.  
  1226.         if (!bp || !*bp) goto any;
  1227.         if (!strncmpi(bp, "an ", l=3) ||
  1228.             !strncmpi(bp, "a ", l=2)) {
  1229.             cnt = 1;
  1230.         } else if (!strncmpi(bp, "the ", l=4)) {
  1231.             ;    /* just increment `bp' by `l' below */
  1232.         } else if (!cnt && digit(*bp)) {
  1233.             cnt = atoi(bp);
  1234.             while(digit(*bp)) bp++;
  1235.             while(*bp == ' ') bp++;
  1236.             l = 0;
  1237.         } else if (!strncmpi(bp, "blessed ", l=8) ||
  1238.                !strncmpi(bp, "holy ", l=5)) {
  1239.             blessed = 1;
  1240.         } else if (!strncmpi(bp, "cursed ", l=7) ||
  1241.                !strncmpi(bp, "unholy ", l=7)) {
  1242.             iscursed = 1;
  1243.         } else if (!strncmpi(bp, "uncursed ", l=9)) {
  1244.             uncursed = 1;
  1245.         } else if (!strncmp(bp, "rustproof ", l=10) ||
  1246.                !strncmp(bp, "erodeproof ", l=11) ||
  1247.                !strncmp(bp, "corrodeproof ", l=13) ||
  1248.                !strncmp(bp, "fireproof ", l=10)) {
  1249.             erodeproof = 1;
  1250.         } else if (!strncmpi(bp,"lit ", l=4) ||
  1251.                !strncmpi(bp,"burning ", l=8)) {
  1252.             islit = 1;
  1253.         } else if (!strncmpi(bp,"unlit ", l=6) ||
  1254.                !strncmpi(bp,"extinguished ", l=13)) {
  1255.             islit = 0;
  1256.         /* "unlabeled" and "blank" are synonymous */
  1257.         } else if (!strncmpi(bp,"unlabeled ", l=10) ||
  1258.                !strncmpi(bp,"unlabelled ", l=11) ||
  1259.                !strncmpi(bp,"blank ", l=6)) {
  1260.             unlabeled = 1;
  1261.         } else if (!strncmpi(bp, "very ", l=5)) {
  1262.             very = 1;
  1263.         } else if (!strncmpi(bp, "thoroughly ", l=11)) {
  1264.             very = 2;
  1265.         } else if (!strncmp(bp, "rusty ", l=6) ||
  1266.                !strncmp(bp, "rusted ", l=7) ||
  1267.                !strncmp(bp, "eroded ", l=7) ||
  1268.                !strncmp(bp, "corroded ", l=9) ||
  1269.                !strncmp(bp, "burnt ", l=6) ||
  1270.                !strncmp(bp, "burned ", l=7) ||
  1271.                !strncmp(bp, "rotted ", l=7)) {
  1272.             eroded = 1 + very; very = 0;
  1273.         } else if (!strncmpi(bp, "very ", l=5)) {
  1274.             /* very rusted very heavy iron ball */
  1275.             very = 1;
  1276.         } else if (!strncmpi(bp, "partly eaten ", l=13)) {
  1277.             halfeaten = 1;
  1278.         } else break;
  1279.         bp += l;
  1280.     }
  1281.     if(!cnt) cnt = 1;        /* %% what with "gems" etc. ? */
  1282. #ifdef TUTTI_FRUTTI
  1283.     Strcpy(fruitbuf, bp);
  1284. #endif
  1285.     if(!strncmpi(bp, "empty ", 6)) {
  1286.         contents = EMPTY;
  1287.         bp += 6;
  1288.     } else if(!strncmpi(bp, "poisoned ",9)) {
  1289.         ispoisoned=1;
  1290.         bp += 9;
  1291. #ifdef WIZARD
  1292.     } else if(wizard && !strncmpi(bp, "trapped ",8)) {
  1293.         ispoisoned=1;
  1294.         bp += 8;
  1295. #endif
  1296.     }
  1297.     if (strlen(bp) > 1) {
  1298.         if (*bp == '+' || *bp == '-') {
  1299.         spesgn = (*bp++ == '+') ? 1 : -1;
  1300.         spe = atoi(bp);
  1301.         while(digit(*bp)) bp++;
  1302.         while(*bp == ' ') bp++;
  1303.         } else if ((p = rindex(bp, '(')) != 0) {
  1304.         if (p > bp && p[-1] == ' ') p[-1] = 0;
  1305.         else *p = 0;
  1306.         p++;
  1307.         if (!strcmpi(p, "lit)"))
  1308.             islit = 1;
  1309.         else {
  1310.             spe = atoi(p);
  1311.             while(digit(*p)) p++;
  1312.             if (*p != ')') spe = 0;
  1313.             else {
  1314.             spesgn = 1;
  1315.             p++;
  1316.             if (*p) Strcat(bp, p);
  1317.             }
  1318.         }
  1319.         }
  1320.     }
  1321. /*
  1322.    otmp->spe is type schar; so we don't want spe to be any bigger or smaller.
  1323.    also, spe should always be positive  -- some cheaters may try to confuse
  1324.    atoi()
  1325. */
  1326.     if (spe < 0) {
  1327.         spesgn = -1;    /* cheaters get what they deserve */
  1328.         spe = abs(spe);
  1329.     }
  1330.     if (spe > SCHAR_LIM)
  1331.         spe = SCHAR_LIM;
  1332.  
  1333.     /* now we have the actual name, as delivered by xname, say
  1334.         green potions called whisky
  1335.         scrolls labeled "QWERTY"
  1336.         egg
  1337.         fortune cookies
  1338.         very heavy iron ball named hoei
  1339.         wand of wishing
  1340.         elven cloak
  1341.     */
  1342.     if ((p = strstri(bp, " named ")) != 0) {
  1343.         *p = 0;
  1344.         name = p+7;
  1345.     }
  1346.     if ((p = strstri(bp, " called ")) != 0) {
  1347.         *p = 0;
  1348.         un = p+8;
  1349.         /* "helmet called telepathy" is not "helmet" (a specific type)
  1350.          * "shield called reflection" is not "shield" (a general type)
  1351.          */
  1352.         for(i = 0; i < SIZE(o_ranges); i++)
  1353.             if(!strcmpi(bp, o_ranges[i].name)) {
  1354.             let = o_ranges[i].osym;
  1355.             goto srch;
  1356.             }
  1357.     }
  1358.     if ((p = strstri(bp, " labeled ")) != 0) {
  1359.         *p = 0;
  1360.         dn = p+9;
  1361.     } else if ((p = strstri(bp, " labelled ")) != 0) {
  1362.         *p = 0;
  1363.         dn = p+10;
  1364.     }
  1365.     if ((p = strstri(bp, " of spinach")) != 0) {
  1366.         *p = 0;
  1367.         contents = SPINACH;
  1368.     }
  1369.  
  1370.     /* Skip over "pair of ", then jump to the singular since we don't
  1371.        need to convert "gloves" or "boots". */
  1372.     if(cnt == 1 && !strncmpi(bp, "pair of ",8)) {
  1373.         bp += 8;
  1374.         cnt = 2;
  1375.         goto sing;
  1376.         /* cnt is ignored for armor and other non-stackable objects;
  1377.            DTRT for stackable objects */
  1378.     } else if(cnt > 1 && !strncmpi(bp, "pairs of ",9)) {
  1379.         bp += 9;
  1380.         cnt *= 2;
  1381.     } else if (!strncmpi(bp, "set of ",7)) {
  1382.         bp += 7;
  1383.     } else if (!strncmpi(bp, "sets of ",8)) {
  1384.         bp += 8;
  1385.     }
  1386.  
  1387.     /*
  1388.      * Find corpse type using "of" (figurine of an orc, tin of orc meat)
  1389.      * Don't check if it's a wand or spellbook.
  1390.      * (avoid "wand/finger of death" confusion).
  1391.      */
  1392.     if (!strstri(bp, "wand ")
  1393.      && !strstri(bp, "spellbook ")
  1394.      && !strstri(bp, "finger ")) {
  1395.         if ((p = strstri(bp, " of ")) != 0
  1396.         && (mntmp = name_to_mon(p+4)) >= 0)
  1397.         *p = 0;
  1398.     }
  1399.     /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
  1400.     if (strncmp(bp, "samurai sword", 13)) /* not the "samurai" monster! */
  1401.     if (strncmp(bp, "wizard lock", 11)) /* not the "wizard" monster! */
  1402.     if (strncmp(bp, "ninja-to", 8)) /* not the "ninja" rank */
  1403.     if (mntmp < 0 && strlen(bp) > 2 && (mntmp = name_to_mon(bp)) >= 0) {
  1404.         int mntmptoo, mntmplen;    /* double check for rank title */
  1405.         char *obp = bp;
  1406.         mntmptoo = title_to_mon(bp, (int *)0, &mntmplen);
  1407.         bp += mntmp != mntmptoo ? strlen(mons[mntmp].mname) : mntmplen;
  1408.         if (*bp == ' ') bp++;
  1409.         else if (!strncmpi(bp, "s ", 2)) bp += 2;
  1410.         else if (!strncmpi(bp, "es ", 3)) bp += 3;
  1411.         else if (!*bp && !actualn && !dn && !un && !let) {
  1412.             /* no referent; they don't really mean a monster type */
  1413.             bp = obp;
  1414.             mntmp = -1;
  1415.         }
  1416.     }
  1417.  
  1418.     /* first change to singular if necessary */
  1419.     if (*bp) {
  1420.         char *sng = makesingular(bp);
  1421.         if (strcmp(bp, sng)) {
  1422.             if (cnt == 1) cnt = 2;
  1423.             Strcpy(bp, sng);
  1424.         }
  1425.     }
  1426.  
  1427. sing:
  1428.     /* Alternate spellings (two-handed sword vs. two handed sword) */
  1429.     {struct alt_spellings *as = spellings;
  1430.         while(as->sp) {
  1431.             if (!strcmpi(bp, as->sp)) {
  1432.                 typ = as->ob;
  1433.                 goto typfnd;
  1434.             }
  1435.             as++;
  1436.         }
  1437.     }
  1438.  
  1439.     /* dragon scales - assumes order of dragons */
  1440.     if(!strcmpi(bp, "scales") &&
  1441.             mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON) {
  1442.         typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
  1443.         mntmp = -1;    /* no monster */
  1444.         goto typfnd;
  1445.     }
  1446.  
  1447.     p = eos(bp);
  1448.     if(!BSTRCMPI(bp, p-10, "holy water")) {
  1449.         typ = POT_WATER;
  1450.         if ((p-bp) >= 12 && *(p-12) == 'u')
  1451.             iscursed = 1; /* unholy water */
  1452.         else blessed = 1;
  1453.         goto typfnd;
  1454.     }
  1455.     if(unlabeled && !BSTRCMPI(bp, p-6, "scroll")) {
  1456.         typ = SCR_BLANK_PAPER;
  1457.         goto typfnd;
  1458.     }
  1459.     if(unlabeled && !BSTRCMPI(bp, p-9, "spellbook")) {
  1460.         typ = SPE_BLANK_PAPER;
  1461.         goto typfnd;
  1462.     }
  1463. #ifdef TOURIST
  1464.     if (!BSTRCMPI(bp, p-5, "shirt")) {
  1465.         typ = HAWAIIAN_SHIRT;
  1466.         goto typfnd;
  1467.     }
  1468. #endif
  1469.     /*
  1470.      * NOTE: Gold pieces are handled as objects nowadays, and therefore
  1471.      * this section should probably be reconsidered as well as the entire
  1472.      * gold/money concept.  Maybe we want to add other monetary units as
  1473.      * well in the future. (TH)
  1474.      */
  1475.     if(!BSTRCMPI(bp, p-10, "gold piece") || !BSTRCMPI(bp, p-7, "zorkmid") ||
  1476.        !strcmpi(bp, "gold") || !strcmpi(bp, "money") || 
  1477.        !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
  1478.             if (cnt > 5000
  1479. #ifdef WIZARD
  1480.                     && !wizard
  1481. #endif
  1482.                         ) cnt=5000;
  1483.         if (cnt < 1) cnt=1;
  1484.         pline("%d gold piece%s.", cnt, plur(cnt));
  1485.         u.ugold += cnt;
  1486.         flags.botl=1;
  1487.         return (&zeroobj);
  1488.     }
  1489.     if (strlen(bp) == 1 &&
  1490.        (i = def_char_to_objclass(*bp)) < MAXOCLASSES && i > ILLOBJ_CLASS) {
  1491.         let = i;
  1492.         goto any;
  1493.     }
  1494.  
  1495.     /* Search for class names: XXXXX potion, scroll of XXXXX.  Avoid */
  1496.     /* false hits on, e.g., rings for "ring mail". */
  1497.     if(strncmpi(bp, "enchant ", 8) &&
  1498.        strncmpi(bp, "destroy ", 8) &&
  1499.        strncmpi(bp, "food detection", 14) &&
  1500.        strncmpi(bp, "ring mail", 9) &&
  1501.        strncmpi(bp, "studded leather arm", 19) &&
  1502.        strncmpi(bp, "leather arm", 11) &&
  1503.        strncmpi(bp, "tooled horn", 11) &&
  1504.        strncmpi(bp, "food ration", 11)
  1505.     )
  1506.     for(i = 0; i < sizeof(wrpsym); i++) {
  1507.         register int j = strlen(wrp[i]);
  1508.         if(!strncmpi(bp, wrp[i], j)){
  1509.             let = wrpsym[i];
  1510.             if(let != AMULET_CLASS) {
  1511.                 bp += j;
  1512.                 if(!strncmpi(bp, " of ", 4)) actualn = bp+4;
  1513.                 /* else if(*bp) ?? */
  1514.             } else
  1515.                 actualn = bp;
  1516.             goto srch;
  1517.         }
  1518.         if(!BSTRCMPI(bp, p-j, wrp[i])){
  1519.             let = wrpsym[i];
  1520.             p -= j;
  1521.             *p = 0;
  1522.             if(p > bp && p[-1] == ' ') p[-1] = 0;
  1523.             actualn = dn = bp;
  1524.             goto srch;
  1525.         }
  1526.     }
  1527.     if (!BSTRCMPI(bp, p-6, " stone")) {
  1528.         p[-6] = 0;
  1529.         let = GEM_CLASS;
  1530.         dn = actualn = bp;
  1531.         goto srch;
  1532.     } else if (!BSTRCMPI(bp, p-6, " glass") || !strcmpi(bp, "glass")) {
  1533.         register char *g = bp;
  1534.         if (strstri(g, "broken")) return (struct obj *)0;
  1535.         if (!strncmpi(g, "worthless ", 10)) g += 10;
  1536.         if (!strncmpi(g, "piece of ", 9)) g += 9;
  1537.         if (!strncmpi(g, "colored ", 8)) g += 8;
  1538.         else if (!strncmpi(g, "coloured ", 9)) g += 9;
  1539.         if (!strcmpi(g, "glass")) {    /* choose random color */
  1540.             /* white, blue, red, yellowish brown, green, violet */
  1541.             typ = LAST_GEM + rnd(6);
  1542.             if (objects[typ].oc_class == GEM_CLASS) goto typfnd;
  1543.             else typ = 0;    /* somebody changed objects[]? punt */
  1544.         } else if (g > bp) {    /* try to construct canonical form */
  1545.             char tbuf[BUFSZ];
  1546.             Strcpy(tbuf, "worthless piece of ");
  1547.             Strcat(tbuf, g);  /* assume it starts with the color */
  1548.             Strcpy(bp, tbuf);
  1549.         }
  1550.     }
  1551. #ifdef WIZARD
  1552.     /* Let wizards wish for traps --KAA */
  1553.     if (wizard) {
  1554.         int trap;
  1555.         char *tname;
  1556.  
  1557.         for (trap = NO_TRAP+1; trap < TRAPNUM; trap++) {
  1558.             tname = index(traps[trap], ' ');
  1559.             if (tname) {
  1560.                 if (!strncmpi(tname+1, bp, strlen(tname+1))) {
  1561.                 /* avoid stupid mistakes */
  1562.                 if(trap == TRAPDOOR && !Can_fall_thru(&u.uz))
  1563.                     trap = ROCKTRAP;
  1564.  
  1565.                 (void) maketrap(u.ux, u.uy, trap);
  1566.                 pline("A%s.", traps[trap]);
  1567.                 return(&zeroobj);
  1568.                 }
  1569.             }
  1570.         }
  1571.         /* or some other dungeon features -dlc */
  1572.         p = eos(bp);
  1573.         if(!BSTRCMP(bp, p-8, "fountain")) {
  1574.             levl[u.ux][u.uy].typ = FOUNTAIN;
  1575.             level.flags.nfountains++;
  1576.             if(!strncmpi(bp, "magic ", 6))
  1577.                 levl[u.ux][u.uy].blessedftn = 1;
  1578.             pline("A %sfountain.",
  1579.                   levl[u.ux][u.uy].blessedftn ? "magic " : "");
  1580.             newsym(u.ux, u.uy);
  1581.             return(&zeroobj);
  1582.         }
  1583. # ifdef SINKS
  1584.         if(!BSTRCMP(bp, p-4, "sink")) {
  1585.             levl[u.ux][u.uy].typ = SINK;
  1586.             level.flags.nsinks++;
  1587.             pline("A sink.");
  1588.             newsym(u.ux, u.uy);
  1589.             return &zeroobj;
  1590.         }
  1591. # endif
  1592.         if(!BSTRCMP(bp, p-5, "altar")) {
  1593.             aligntyp al;
  1594.  
  1595.             levl[u.ux][u.uy].typ = ALTAR;
  1596.             if(!strncmpi(bp, "chaotic ", 8))
  1597.             al = A_CHAOTIC;
  1598.             else if(!strncmpi(bp, "neutral ", 8))
  1599.             al = A_NEUTRAL;
  1600.             else if(!strncmpi(bp, "lawful ", 7))
  1601.             al = A_LAWFUL;
  1602.             else if(!strncmpi(bp, "unaligned ", 10))
  1603.             al = A_NONE;
  1604.             else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
  1605.             al = (!rn2(6)) ? A_NONE : rn2((int)A_LAWFUL+2) - 1;
  1606.             levl[u.ux][u.uy].altarmask = Align2amask( al );
  1607.             pline("%s altar.", An(align_str(al)));
  1608.             newsym(u.ux, u.uy);
  1609.             return(&zeroobj);
  1610.         }
  1611.     }
  1612. #endif
  1613.     for (i = 0; i < SIZE(o_ranges); i++)
  1614.         if(!strcmpi(bp, o_ranges[i].name)) {
  1615.         typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
  1616.         goto typfnd;
  1617.         }
  1618.  
  1619.     actualn = bp;
  1620.     if (!dn) dn = actualn; /* ex. "skull cap" */
  1621. srch:
  1622.     /* check real names of gems first */
  1623.     if(!let && actualn) {
  1624.         for(i = bases[letindex(GEM_CLASS)]; i <= LAST_GEM; i++) {
  1625.         register const char *zn;
  1626.  
  1627.         if((zn = OBJ_NAME(objects[i])) && !strcmpi(actualn, zn)) {
  1628.             typ = i;
  1629.             goto typfnd;
  1630.         }
  1631.         }
  1632.     }
  1633.     i = 1;
  1634.     if(let) i = bases[letindex(let)];
  1635.     while(i <= NROFOBJECTS && (!let || objects[i].oc_class == let)){
  1636.         register const char *zn;
  1637.  
  1638.         if(actualn && (zn = OBJ_NAME(objects[i])) && !strcmpi(actualn, zn)) {
  1639.             typ = i;
  1640.             goto typfnd;
  1641.         }
  1642.         if(dn && (zn = OBJ_DESCR(objects[i])) && !strcmpi(dn, zn)) {
  1643.             /* don't match extra descriptions (w/o real name) */
  1644.             if (!OBJ_NAME(objects[i])) return (struct obj *)0;
  1645.             typ = i;
  1646.             goto typfnd;
  1647.         }
  1648.         if(un && (zn = objects[i].oc_uname) && !strcmpi(un, zn)) {
  1649.             typ = i;
  1650.             goto typfnd;
  1651.         }
  1652.         i++;
  1653.     }
  1654.     if (actualn) {
  1655.         struct Jitem *j = Japanese_items;
  1656.         while(j->item) {
  1657.             if (actualn && !strcmpi(actualn, j->name)) {
  1658.                 typ = j->item;
  1659.                 goto typfnd;
  1660.             }
  1661.             j++;
  1662.         }
  1663.     }
  1664. #ifdef TUTTI_FRUTTI
  1665.     /* Note: not strncmpi.  2 fruits, one capital, one not, is possible. */
  1666.     for(f=ffruit; f; f = f->nextf) {
  1667.         char *f1 = f->fname, *f2 = makeplural(f->fname);
  1668.  
  1669.         if(!strncmp(fruitbuf, f1, strlen(f1)) ||
  1670.                     !strncmp(fruitbuf, f2, strlen(f2))) {
  1671.             typ = SLIME_MOLD;
  1672.             ftype = f->fid;
  1673.             goto typfnd;
  1674.         }
  1675.     }
  1676. #endif
  1677.     if (!strcmpi(bp, "spinach")) {
  1678.         contents = SPINACH;
  1679.         typ = TIN;
  1680.         goto typfnd;
  1681.     }
  1682.  
  1683.     if(!let && actualn) {
  1684.         short objtyp;
  1685.  
  1686.         /* Perhaps it's an artifact specified by name, not type */
  1687.         name = artifact_name(actualn, &objtyp);
  1688.         if(name) {
  1689.         typ = objtyp;
  1690.         goto typfnd;
  1691.         }
  1692.     }
  1693.     if(!let) return((struct obj *)0);
  1694. any:
  1695.     if(!let) let = wrpsym[rn2((int)sizeof(wrpsym))];
  1696. typfnd:
  1697.     if (typ) let = objects[typ].oc_class;
  1698.  
  1699.     /* check for some objects that are not allowed */
  1700.     if (typ && objects[typ].oc_unique
  1701. #ifdef WIZARD
  1702.         && !wizard 
  1703.         /* should check flags.made_amulet, but it's not set anywhere */
  1704. #endif
  1705.        )
  1706.         switch (typ) {
  1707.         case AMULET_OF_YENDOR:
  1708.             typ = FAKE_AMULET_OF_YENDOR;
  1709.             break;
  1710.         case CANDELABRUM_OF_INVOCATION:
  1711.             typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
  1712.             break;
  1713.         case BELL_OF_OPENING:
  1714.             typ = BELL;
  1715.             break;
  1716.         case SPE_BOOK_OF_THE_DEAD:
  1717.             typ = SPE_BLANK_PAPER;
  1718.             break;
  1719.         }
  1720.     /* catch any other non-wishable objects */
  1721.     if (objects[typ].oc_nowish
  1722. #ifdef WIZARD
  1723.         && !wizard
  1724. #endif
  1725.         )
  1726.         return((struct obj *)0);
  1727.  
  1728.     if(typ) {
  1729.         otmp = mksobj(typ, TRUE, FALSE);
  1730.     } else {
  1731.         otmp = mkobj(let, FALSE);
  1732.         if (otmp) typ = otmp->otyp;
  1733.     }
  1734.  
  1735.     if(typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN)
  1736.         otmp->lamplit = islit;
  1737.  
  1738.     if(cnt > 0 && objects[typ].oc_merge && let != SPBOOK_CLASS && 
  1739.         (cnt < rnd(6) ||
  1740. #ifdef WIZARD
  1741.         wizard ||
  1742. #endif
  1743.          (cnt <= 7 && Is_candle(otmp)) ||
  1744.          (cnt <= 20 &&
  1745.           ((let == WEAPON_CLASS && typ <= SHURIKEN) || (typ == ROCK)))))
  1746.             otmp->quan = (long) cnt;
  1747.  
  1748. #ifdef WIZARD
  1749.     if (let == VENOM_CLASS) otmp->spe = 1;
  1750. #endif
  1751.  
  1752.     if (spesgn == 0) spe = otmp->spe;
  1753. #ifdef WIZARD
  1754.     else if (wizard) /* no alteration to spe */ ;
  1755. #endif
  1756.     else if (let == ARMOR_CLASS || let == WEAPON_CLASS || typ == PICK_AXE ||
  1757.             typ == UNICORN_HORN ||
  1758.             (let==RING_CLASS && objects[typ].oc_charged)) {
  1759.         if(spe > rnd(5) && spe > otmp->spe) spe = 0;
  1760.         if(spe > 2 && Luck < 0) spesgn = -1;
  1761.     } else {
  1762.         if (let == WAND_CLASS) {
  1763.             if (spe > 1 && spesgn == -1) spe = 1;
  1764.         } else {
  1765.             if (spe > 0 && spesgn == -1) spe = 0;
  1766.         }
  1767.         if (spe > otmp->spe) spe = otmp->spe;
  1768.     }
  1769.  
  1770.     if (spesgn == -1) spe = -spe;
  1771.  
  1772.     /* set otmp->spe.  This may, or may not, use spe... */
  1773.     switch (typ) {
  1774.         case TIN: if (contents==EMPTY) {
  1775.                 otmp->corpsenm = -1;
  1776.                 otmp->spe = 0;
  1777.             } else if (contents==SPINACH) {
  1778.                 otmp->corpsenm = -1;
  1779.                 otmp->spe = 1;
  1780.             }
  1781.             break;
  1782. #ifdef TUTTI_FRUTTI
  1783.         case SLIME_MOLD: otmp->spe = ftype;
  1784.             /* Fall through */
  1785. #endif
  1786.         case SKELETON_KEY: case CHEST: case LARGE_BOX:
  1787.         case HEAVY_IRON_BALL: case IRON_CHAIN: case STATUE:
  1788.             /* otmp->cobj already done in mksobj() */
  1789.                 break;
  1790. #ifdef MAIL
  1791.         case SCR_MAIL: otmp->spe = 1; break;
  1792. #endif
  1793.         case WAN_WISHING:
  1794. #ifdef WIZARD
  1795.             if (!wizard) {
  1796. #endif
  1797.                 otmp->spe = (rn2(10) ? -1 : 0);
  1798.                 break;
  1799. #ifdef WIZARD
  1800.             }
  1801.             /* fall through (twice), if wizard */
  1802. #endif
  1803.         case MAGIC_LAMP:
  1804. #ifdef WIZARD
  1805.             if (!wizard) {
  1806. #endif
  1807.                 otmp->spe = 0;
  1808.                 break;
  1809. #ifdef WIZARD
  1810.             }
  1811.             /* fall through, if wizard */
  1812. #endif
  1813.         default: otmp->spe = spe;
  1814.     }
  1815.  
  1816.     /* set otmp->corpsenm or dragon scale [mail] */
  1817.     if (mntmp > -1) switch(typ) {
  1818.         case TIN:
  1819.             otmp->spe = 0; /* No spinach */
  1820.         case CORPSE:
  1821.             if (!(mons[mntmp].geno & (G_UNIQ | G_NOCORPSE)))
  1822.                 otmp->corpsenm = mntmp;
  1823.             break;
  1824.         case FIGURINE:
  1825.             if (!(mons[mntmp].geno & G_UNIQ)
  1826.                 && !is_human(&mons[mntmp]))
  1827.                 otmp->corpsenm = mntmp;
  1828.             break;
  1829.         case EGG: if (lays_eggs(&mons[mntmp]) || mntmp==PM_KILLER_BEE)
  1830.                 otmp->corpsenm = mntmp;
  1831.             break;
  1832.         case STATUE: otmp->corpsenm = mntmp;
  1833.             break;
  1834.         case SCALE_MAIL:
  1835.             /* Dragon mail - depends on the order of objects */
  1836.             /*         & dragons.             */
  1837.                 if (mntmp >= PM_GRAY_DRAGON &&
  1838.                         mntmp <= PM_YELLOW_DRAGON)
  1839.                 otmp->otyp = GRAY_DRAGON_SCALE_MAIL +
  1840.                             mntmp - PM_GRAY_DRAGON;
  1841.             break;
  1842.     }
  1843.  
  1844.     /* set blessed/cursed -- setting the fields directly is safe
  1845.      * since weight() is called below and addinv() will take care
  1846.      * of luck */
  1847.     if (iscursed) {
  1848.         curse(otmp);
  1849.     } else if (uncursed) {
  1850.         otmp->blessed = 0;
  1851.         otmp->cursed = (Luck < 0
  1852. #ifdef WIZARD
  1853.                      && !wizard
  1854. #endif
  1855.                             );
  1856.     } else if (blessed) {
  1857.         otmp->blessed = (Luck >= 0
  1858. #ifdef WIZARD
  1859.                      || wizard
  1860. #endif
  1861.                             );
  1862.         otmp->cursed = (Luck < 0
  1863. #ifdef WIZARD
  1864.                      && !wizard
  1865. #endif
  1866.                             );
  1867.     } else if (spesgn < 0) {
  1868.         curse(otmp);
  1869.     }
  1870.  
  1871.     /* set eroded */
  1872.     if (eroded)
  1873.         otmp->oeroded = eroded;
  1874.  
  1875.     /* set erodeproof */
  1876.     else if (erodeproof)
  1877.         otmp->oerodeproof = (Luck >= 0
  1878. #ifdef WIZARD
  1879.                      || wizard
  1880. #endif
  1881.                     );
  1882.  
  1883.     /* prevent wishing abuse */
  1884.     if (
  1885. #ifdef WIZARD
  1886.         !wizard &&
  1887. #endif
  1888.             otmp->otyp == WAN_WISHING)
  1889.         otmp->recharged = 1;
  1890.  
  1891.     /* set poisoned */
  1892.     if (ispoisoned) {
  1893.         if (let == WEAPON_CLASS && typ <= SHURIKEN)
  1894.         otmp->opoisoned = (Luck >= 0);
  1895.         else if (Is_box(otmp) || typ == TIN)
  1896.         otmp->otrapped = 1;
  1897.         else if (let == FOOD_CLASS)
  1898.         /* try to taint by making it as old as possible */
  1899.             otmp->age = 1L;
  1900.     }
  1901.  
  1902.     if (name) {
  1903.         otmp = oname(otmp, name, 0);
  1904.         if (otmp->oartifact) otmp->quan = 1L;
  1905.     }
  1906.  
  1907. #ifdef MULDGN
  1908.     /* more wishing abuse: don't allow wishing for certain artifacts */
  1909.     /* and make them pay; charge them for the wish anyway! */
  1910.     if ((is_quest_artifact(otmp) || 
  1911.          (otmp->oartifact && rn2(nartifact_exist()) > 1))
  1912. # ifdef WIZARD
  1913.         && !wizard
  1914. # endif
  1915.         ) {
  1916.         artifact_unexist(otmp);
  1917.         obfree(otmp, (struct obj *) 0);
  1918.         otmp = &zeroobj;
  1919.         pline(
  1920.          "For a moment, you feel something in your %s, but it disappears!",
  1921.           makeplural(body_part(HAND)));
  1922.     }
  1923. #endif    /* MULDGN */
  1924.  
  1925.     otmp->owt = weight(otmp);
  1926.     if (very && otmp->otyp == HEAVY_IRON_BALL) otmp->owt += 160;
  1927.     if (halfeaten && otmp->oclass == FOOD_CLASS) {
  1928.         if (otmp->otyp == CORPSE)
  1929.             otmp->oeaten = mons[otmp->corpsenm].cnutrit;
  1930.         else otmp->oeaten = objects[otmp->otyp].oc_nutrition;
  1931.         otmp->owt /= 2;
  1932.         otmp->oeaten /= 2;
  1933.         if (!otmp->owt) otmp->owt = 1;
  1934.         if (!otmp->oeaten) otmp->oeaten = 1;
  1935.     }
  1936.     return(otmp);
  1937. }
  1938.  
  1939. int
  1940. rnd_class(first,last)
  1941. int first,last;
  1942. {
  1943.     int i, x, sum=0;
  1944.     for(i=first; i<=last; i++)
  1945.         sum += objects[i].oc_prob;
  1946.     if (!sum) /* all zero */
  1947.         return first + rn2(last-first+1);
  1948.     x = rnd(sum);
  1949.     for(i=first; i<=last; i++)
  1950.         if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
  1951.             return i;
  1952.     return 0;
  1953. }
  1954.  
  1955. STATIC_OVL const char *
  1956. Japanese_item_name(i)
  1957. int i;
  1958. {
  1959.     struct Jitem *j = Japanese_items;
  1960.  
  1961.     while(j->item) {
  1962.         if (i == j->item)
  1963.             return j->name;
  1964.         j++;
  1965.     }
  1966.     return (const char *)0;
  1967. }
  1968. #endif /* OVLB */
  1969.  
  1970. /*objnam.c*/
  1971.